#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <functional>

using func = std::function<void(std::string &, pthread_mutex_t *, pthread_cond_t *)>;

bool quit = false; //线程退出

// 线程函数传参对象
class ThreadDate
{
public:
    ThreadDate(std::string &name, int index, pthread_mutex_t *pmutex, pthread_cond_t *pcond)
        : _name(name), _index(index), _pmutex(pmutex), _pcond(pcond)
    {
    }

public:
    std::string _name;        // 线程名
    int _index;               // 函数下标
    pthread_mutex_t *_pmutex; // 互斥锁
    pthread_cond_t *_pcond;   // 条件变量
};

int cnt = 0; // 全局变量（临界资源）

void func1(std::string &name, pthread_mutex_t *pmutex, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmutex);       // 加锁
        pthread_cond_wait(pcond, pmutex); // 等待条件变量
        std::cout << name << "  task 1 " << "cnt: " << cnt++ << std::endl;
        pthread_mutex_unlock(pmutex); // 解锁
        // sleep(1);
    }
}

void func2(std::string &name, pthread_mutex_t *pmutex, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmutex);       // 加锁
        pthread_cond_wait(pcond, pmutex); // 等待条件变量
        std::cout << name << "  task 2 " << "cnt: " << cnt++ << std::endl;
        pthread_mutex_unlock(pmutex); // 解锁
        // sleep(1);
    }
}

void func3(std::string &name, pthread_mutex_t *pmutex, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmutex);       // 加锁
        pthread_cond_wait(pcond, pmutex); // 等待条件变量
        std::cout << name << "  task 3 " << "cnt: " << cnt++ << std::endl;
        pthread_mutex_unlock(pmutex); // 解锁
        // sleep(1);
    }
}

func funcs[] = {func1, func2, func3};

void *Entry(void *args)
{
    ThreadDate *arg = (ThreadDate *)args;
    // 执行函数
    funcs[arg->_index](arg->_name, arg->_pmutex, arg->_pcond);

    delete arg;
    return nullptr;
}

int main()
{
    // 创建条件变量和互斥锁
    pthread_cond_t cond;   // 条件变量
    pthread_mutex_t mutex; // 互斥锁

    // 初始化
    pthread_cond_init(&cond, nullptr);
    pthread_mutex_init(&mutex, nullptr);

    // 创建线程
    pthread_t tids[3];
    for (int i = 0; i < 3; i++)
    {
        std::string name = "Thread";
        name += std::to_string(i);
        ThreadDate *td = new ThreadDate(name, i, &mutex, &cond);
        pthread_create(tids + i, nullptr, Entry, (void *)td);
    }

    sleep(3);
    int count = 5;
    while (count--)
    {
        // 唤醒条件变量
        // pthread_cond_signal(&cond); // 每次只唤醒一个线程
        pthread_cond_broadcast(&cond); // 唤醒全部线程
        sleep(1);
    }

    quit = true; // 线程退出
    pthread_cond_broadcast(&cond); // 唤醒全部线程


    // 回收线程
    for (int i = 0; i < 3; i++)
    {
        pthread_join(tids[i], nullptr);
        std::cout << "Thread " << i << " quit" << std::endl;
    }

    // 销毁条件变量和互斥锁
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);

    return 0;
}